package top.hudk.peakclipping;

import java.util.*;

/**
 * 作用：削峰统计类
 *
 * @author hudk
 * @date 2020/12/16 16:40 CircularLinkedPeakClippingStatistician
 */
public class PeakClippingStatistician {

    /**
     * 请求临时存放池
     * 存放还处于时间窗口内的请求信息
     */
    private static List<Request> requestList = null;

    /**
     * 时间窗口长度
     */
    private final static long time = 1000;

    /**
     * 请求阈值
     * 时间窗口期内，最大接收的请求数
     */
    private final static long threshold = 10;

    static {
        requestList = new LinkedList<>();
    }

    /**
     * 作用：
     *
     * @author hudk
     * @date 2020/12/16 16:42
     */
    static class Request {

        public Request(){
            this.timestamp = System.currentTimeMillis();
        }

        /**
         * 时间戳
         */
        private long timestamp;

        public long getTimestamp() {
            return timestamp;
        }

        public void setTimestamp(long timestamp) {
            this.timestamp = timestamp;
        }
    }

    /**
     * 流量检查，判断调用频次是否达到阈值
     * @return
     */
    public static synchronized Boolean check() {

        System.out.println("时间窗口累计请求数：" + requestList.size());
        //首先判断当目前暂存的请求数量加上新的这个请求，总数量小于等于阈值的话，
        // 新请求被允许，并将新请求加入暂存列表
        if (requestList.size() + 1 <= threshold){
            requestList.add(new Request());
            return true;
        }
        //从尾部向前遍历整个请求列表，将请求间隔超过指定时间间隙的请求删除
        for (int i = requestList.size() - 1; i >= 0 ; i--) {
            Request request = requestList.get(i);
            long currentTimeMillis = System.currentTimeMillis();
            //当下时间距请求发生的时间，如果超过指定时间间隙，则将该请求信息从列表删除
            if (currentTimeMillis - request.getTimestamp() > time) {
                requestList.remove(request);
            }
        }
        //判断剩余的请求数量
        if (requestList.size() >= threshold) {
            return false;
        }
        requestList.add(new Request());
        return true;
    }

}
